package com.example.shiwu.util;

import static androidx.constraintlayout.motion.utils.Oscillator.TAG;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Create by Fiora on 2018/10/24 0024
 */
public class TcpService extends Service {
    public static final String TAG = TcpService.class.getSimpleName();

    private BufferedInputStream bis;
    private BufferedOutputStream bos;
    private SocketUtils.OnMessageReceivedListener messageListener;
    private Callback callback;


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new ClientBinder();
    }

    public class Binder extends android.os.Binder {
        public TcpService getService() {
            return TcpService.this;
        }
    }

    public void setCallback(Callback callback) {
        this.callback = callback;
    }

    public static interface Callback {
        void onDataChange(String data);
    }


    public class ClientBinder extends Binder {
        private int mHeart_spacetime = 3000; //心跳间隔时间

        private ReadThread mReadThread;
        private Handler mHandler = new Handler();
        private Socket mSocket;
        private ExecutorService mExecutorService;
        private int tryCount = 0;//重试次数
        public int success_count = 0;

        public String msg_0 = "";
        public String msg_1 = "";
        public String receiveDataAll = "";
        private String cmd_index_len = "";//消息的id 10
        public Integer packet_lens = 0;
        public Integer packet_indx = 0;
        public int packet_lens_old = 0;

        private synchronized String receive_one_field(int sta) throws InterruptedException, UnsupportedEncodingException {
            Map<String, Object> map = new HashMap<>();
            Boolean escaped = false;
            Boolean command_sep_found = false;
            ArrayList<Byte> one_field = new ArrayList<Byte>();
            Boolean timeout = false;
            Boolean bl = true;
            String msgbt = "";
            while (bl) {
                byte tmp = this.read();
                byte[] b = new byte[1];
                b[0] = tmp;
                if (sta == 1) {
                    msgbt += new String(b, "utf-8");
                } else {
                    msgbt += new String(b, "iso8859-1");
                }

                if (escaped) {
                    if (tmp == 44 || tmp == 59 || tmp == 47) {
                        one_field.add(tmp);
                        escaped = false;
                    } else {
                        one_field.add(tmp);
                        escaped = false;
                    }
                } else {
                    if (tmp == 47) {
                        //遇到 / 就escaped = True 继续循环
                        escaped = true;
                    } else if (tmp == 44) {
                        break;
                    } else if (tmp == 59) {
                        command_sep_found = true;
                        break;
                    } else {
                        one_field.add(tmp);
                    }
                }

            }

            map.put("one_field", one_field);
            map.put("timeout", timeout);
            return msgbt;
        }

        public void writeMsg(String msg) {
            //Log.i(TAG, "writeMsg msg=" + msg);
            if (msg.length() == 0 || bos == null)
                return;
            try {
                bos.write(msg.getBytes());//发送
                bos.flush();
                //Log.i(TAG, "-----------------writeMsg msg ="+ msg);
                Log.i(TAG, "-----------------writeMsg msg ="+ msg+"   success_count====="+success_count);


            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        public void writeMsgByte(byte[] msg) {

//        Log.i(TAG, "------------------------------------------------writeMsgByte msg=" + msg +"mReceiveThread.isAlive() ="+mReceiveThread.getState());
//        Log.i(TAG, "------------------------------------------------writeMsgByte msg mOutStream=" + mOutStream);
            if (msg.length == 0 || bos == null)
                return;
            try {
                bos.write(msg);//发送
                bos.flush();
                //Log.i(TAG, "-----------------writeMsgByte msg ="+ new String(msg,"iso8859-1")+"   success_count====="+success_count);

            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        public synchronized byte read() {

            byte[] buffer = new byte[1];
            try {
                bis.read(buffer);
//            BufferedInputStream bis = new BufferedInputStream(mInputStream);
//            bis.read(buffer);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return buffer[0];
        }

        public void startConnect() {
            //在子线程进行网络操作
            // Service也是运行在主线程，千万不要以为Service意思跟后台运行很像，就以为Service运行在后台子线程
            if (mExecutorService == null) {
                mExecutorService = Executors.newCachedThreadPool();
            }

        }

        private Runnable connectRunnable = new Runnable() {
            @Override
            public void run() {
                try {
                    // 建立Socket连接
                    mSocket = new Socket(ContextVariable.IP, ContextVariable.POST);
                    //mSocket.connect(new InetSocketAddress(ContextVariable.IP, ContextVariable.POST), 5);
                    //mSocket.setSoTimeout(10000);
                    bis = new BufferedInputStream(mSocket.getInputStream());
                    bos = new BufferedOutputStream(mSocket.getOutputStream());
                    // 创建读取服务器心跳的线程

                    mReadThread = new ReadThread();
                    mReadThread.start();

                    //开启心跳,每隔1秒钟发送一次心跳
                    //mHandler.post(mHeartRunnable);
                    tryCount = 1;
                    Log.i("Socket", "------------Socket连接成功-------------");
                    writeMsg("22,M;");
                } catch (Exception e) {
                    tryCount++;
                    e.printStackTrace();
                    Log.i(TAG, "Socket连接建立失败,正在尝试第" + tryCount + "次重连");
                    mHandler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            mExecutorService.execute(connectRunnable);
                        }
                    }, mHeart_spacetime);
                }
            }
        };

        public void resumeThread() {
            mReadThread.resumeThread();
        }

        public class ReadThread extends Thread {

            public final Object lock = new Object();
            public boolean threadExit;

            public ReadThread() {
                threadExit = false;
            }

            /**
             * 调用这个方法实现暂停线程
             */
            public void pauseThread() {
                threadExit = true;
            }

            /**
             * 调用这个方法实现恢复线程的运行
             */
            public void resumeThread() {
                threadExit = false;
                synchronized (lock) {
                    lock.notifyAll();
                }
            }

            public void threadExit() {
                threadExit = true;
            }

            /**
             * 注意：这个方法只能在run方法里调用，不然会阻塞主线程，导致页面无响应
             */
            public void onPause() {
                synchronized (lock) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }

            @Override
            public void run() {
                while (threadExit == false) {
//                try {
//                    Thread.sleep(1);
//                } catch (InterruptedException e) {
//                    throw new RuntimeException(e);
//                }
//                writeMsg("13,update;");
//                System.out.println(" =============== 13,update;");
//                if(receive_count==1){
//                    this.onPause();
//                }
                    //System.out.println("-------threadExit1111111111111111111111111 == ");
                    try {
                        byte[] buffer = new byte[1];
                        //读取数据，返回值表示读到的数据长度。-1表示结束
                        int count = 0;
                        try {
                            //基于字符的读取或基于字节的读取
                            Log.i(TAG, "---- buffer = "+new String(buffer, "utf-8"));
                            if (bis.available() > 0) { //添加这里的判断
                                //System.out.println("---- buffer = "+new String(buffer, "iso8859-1"));
                                count = bis.read(buffer);
                                //int bytesRead = mInputStream.read(buffer);
                                if (count == -1) {
                                    Log.i(TAG, "read -1");
                                    break;
                                } else {
                                    //System.out.println("---- buffer = "+buffer);

                                    if (success_count <= 5) {
                                        String msg00 = new String(buffer, "utf-8");
                                        msg_0 += new String(buffer, "utf-8");
                                        System.out.println("---msg00 =" + msg00+" - "+buffer[0]);
                                        try {
                                            if (msg00.equals("??")) {
                                                System.out.println("PC usb dis-connected");
                                                throw new Exception("PC usb dis-connected");
                                            }
                                        } catch (Exception e) {
                                            e.printStackTrace();
                                        }
                                        String obj = receive_one_field(1);//过滤header
                                        String msg_all = msg_0 += obj;
                                        //System.out.println("---msg_all =" + msg_all);

                                        if (msg_all.length() > 2) { //msg_all(0,success) len超过2 也就是0，就可以返回了
                                            if (!msg_all.equals("0,wait;")) {
                                                success_count += 1;
                                            }
                                            //messageListener.onMessageReceivedString(msg_all);
                                            if (callback != null) {
                                                callback.onDataChange(msg_all);
                                            }
                                            msg_0 = "";
                                        }

                                    } else if (success_count == 6) {
                                        msg_0 = new String(buffer, "iso8859-1");

                                        //System.out.println("---msg msg_0 =" + msg_0);
                                        try {
                                            if (msg_0.equals("??")) {
                                                System.out.println("PC usb dis-connected");
                                                throw new Exception("PC usb dis-connected");
                                            }
                                        } catch (Exception e) {
                                            e.printStackTrace();
                                        }
                                        String obj = receive_one_field(2);//过滤header
                                        String msg_all = msg_0 += obj;
                                        //System.out.println("---msg_all11 =" + msg_all);
                                        String msg_all_last = msg_all.substring(msg_all.length() - 1, msg_all.length());
                                        if (!msg_all_last.equals(";")) {
                                            msg_1 += msg_all;
                                            continue;
                                        }
                                        if (msg_all_last.equals(";")) { //msg_all(10,8) 截取数据
                                            success_count += 1;
                                            msg_1 += msg_all;
                                            receiveDataAll += msg_1;
                                            //System.out.println("---receiveDataAll =" + receiveDataAll);
                                            if (success_count == 7) {
                                                cmd_index_len = DataParseUtil.getDataForHeaderIndex(receiveDataAll);
                                                packet_indx = Integer.valueOf(DataParseUtil.initPython(cmd_index_len.split(",")[1]));

                                                packet_lens = Integer.valueOf(DataParseUtil.initPython(cmd_index_len.split(",")[2]));
                                                // System.out.println("--------mReceiveThread22222  packet_indx=="+packet_indx+" = "+packet_lens+" = "+success_count);
                                                packet_lens_old = packet_lens;
                                                DataParseUtil.setPageLens(packet_lens);
                                                receiveDataAll = "";
                                            }
                                            msg_0 = "";
                                            msg_1 = "";
                                        }

                                    } else {
                                        if (success_count == 7) {
                                            //Log.i("buffer","-------------success_count =7" );
                                            success_count += 1;
                                            this.onPause();
                                            continue;
                                        }
                                        if (success_count > 7) {
                                            //Log.i("buffer","-------------success_count >6 -----------= " + new String(buffer));
                                            //Log.i("buffer","-------------success_count >6 -----------= " + buffer[0]);
//                                        messageListener.onMessageReceived(buffer[0]);
//                                        buffer = null;
                                        }
                                    }
                                }
                                //this.pauseThread();
                            } else {
                                this.pauseThread();
                            }

                        } catch (Exception e) {
                            tryCount++;
                            e.printStackTrace();
                            Log.d(TAG, "Socket连接建立失败,正在尝试第" + tryCount + "次重连");
                            mHandler.postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    mExecutorService.execute(connectRunnable);
                                }
                            }, mHeart_spacetime);
                        }

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    //收到心跳消息以后，首先移除断连消息，然后创建一个新的60秒后执行断连的消息。
                    //这样每次收到心跳后都会重新创建一个60秒的延时消息，在60秒后还没收到心跳消息，表明服务器已死，就会执行断开Socket连接
                    //在60秒钟内如果收到过一次心跳消息，就表明服务器还活着，可以继续与之通讯。
                    mHandler.removeCallbacks(disConnectRunnable);
                    mHandler.postDelayed(disConnectRunnable, mHeart_spacetime * 40);

                }

            }
        }

        private Runnable mHeartRunnable = new Runnable() {
            @Override
            public void run() {
                sendData();
            }
        };

        private void sendData() {
            mExecutorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        bos.write("13,update;".getBytes());
                        //一定不能忘记这步操作
                        bos.flush();
                        //发送成功以后，重新建立一个心跳消息
                        mHandler.postDelayed(mHeartRunnable, mHeart_spacetime);
                        Log.d(TAG, "我发送给服务器的消息: 给你一张过去的CD,听听那时我们的爱情！");
                    } catch (Exception e) {
                        e.printStackTrace();
                        Log.d(TAG, "心跳任务发送失败，正在尝试第" + tryCount + "次重连");
                        //mExecutorService.schedule(connectRunnable,mHeart_spacetime, TimeUnit.SECONDS);
                        mExecutorService.execute(connectRunnable);
                    }
                }
            });
        }

        private Runnable disConnectRunnable = new Runnable() {
            @Override
            public void run() {
                disConnect();
            }
        };

        public void disConnect() {
            mExecutorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        Log.d(TAG, "正在执行断连: disConnect");
                        //执行Socket断连
                        mHandler.removeCallbacks(mHeartRunnable);
                        if (mReadThread != null) {
                            mReadThread.interrupt();
                        }

                        if (bos != null) {
                            bos.close();
                        }

                        if (bis != null) {
                            bis.close();
                        }

                        if (mSocket != null) {
                            mSocket.shutdownInput();
                            mSocket.shutdownOutput();
                            mSocket.close();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
}
